package fun.diaoer.common;

import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;

public class BeanUtil extends BeanUtils {

	/**
	 * 获取所有属性名
	 * 
	 * @param clazz
	 * @return
	 */
	public static String[] getProperties(Class<?> clazz) {
		List<String> properties = new ArrayList<String>();
		PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(clazz);
		for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
			properties.add(propertyDescriptor.getName());
		}
		return properties.toArray(new String[properties.size()]);
	}

	/**
	 * 根据属性名获取对象属性值（支持A.B.C模式）
	 * 
	 * @param bean
	 * @param property
	 * @return
	 */
	public static Object getProperty(Object bean, String property) {
		try {
			if (bean == null || StringUtil.isBlank(property))
				return null;

			if (property.indexOf(".") >= 0) {
				String currProp = StringUtil.substring(property, property.indexOf("."));
				if (StringUtil.isNotBlank(currProp)) {
					bean = PropertyUtils.getProperty(bean, currProp);
				}
				property = property.substring(property.indexOf(".") + 1);
				return getProperty(bean, property);
			} else {
				return PropertyUtils.getProperty(bean, property);
			}
		} catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * Copy部分属性
	 * 
	 * @param source
	 * @param target
	 * @param properties
	 * @throws BeansException
	 */
	public static void copyPartProperties(Object source, Object target, String... properties) throws BeansException {
		// 全部属性
		List<String> sourceProperties = new ArrayList<String>();
		Collections.addAll(sourceProperties, getProperties(source.getClass()));
		// 忽略属性
		List<String> ignoreProperties = new ArrayList<String>();
		// 赋值属性
		List<String> copyProperties = new ArrayList<String>();
		Collections.addAll(copyProperties, properties);

		for (String property : sourceProperties) {
			if (!copyProperties.contains(property))
				ignoreProperties.add(property);
		}

		copyProperties(source, target, ignoreProperties.toArray(new String[ignoreProperties.size()]));
	}

	/**
	 * 根据注解获取主键字段
	 * 
	 * @param entity
	 * @return
	 */
	public static String getEntityUuidProperty(final Object entity) {
		if (entity == null)
			return null;

		return getClassUuidProperty(entity.getClass());
	}

	public static String getClassUuidProperty(Class<?> clazz) {
		if (clazz == null)
			return null;
		Field[] fields = clazz.getDeclaredFields();// 所有属性
		for (Field field : fields) {
			for (Annotation annotation : field.getAnnotations()) {
				if (annotation.toString().contains("@javax.persistence.Id()")) {
					return field.getName();
				}
			}
		}
		// 找不到ID去基类里面找
		return getClassUuidProperty(clazz.getSuperclass());
	}

	/**
	 * 获取CLASS所有Field
	 */
	public static Field[] getClassField(Class<?> clazz) {
		if (clazz == null)
			return null;

		List<Field> fields = new ArrayList<>();
		fields.addAll(Arrays.asList(clazz.getDeclaredFields()));

		// 父类属性
		Field[] parentFields = getClassField(clazz.getSuperclass());
		if (parentFields != null && parentFields.length > 0)
			fields.addAll(Arrays.asList(parentFields));
		return fields.toArray(new Field[fields.size()]);
	}

	public static Field getClassField(Class<?> clazz, String name) {
		if (clazz == null || StringUtil.isBlank(name))
			return null;

		Field field = null;
		try {
			field = clazz.getDeclaredField(name);
		} catch (Exception e) {
		}

		if (field == null && clazz.getSuperclass() != null)
			return getClassField(clazz.getSuperclass(), name);

		return field;
	}

	/**
	 * 转化Result的类型
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public static <E> List<E> transferListType(List list, Class<E> clazz) {
		if (list == null || clazz == null)
			return null;

		List newRst = new ArrayList(list.size());
		if (list.size() <= 0)
			return newRst;

		Class origClazz = list.get(0).getClass();
		if (StringUtil.equals(origClazz.getName(), clazz.getName()))
			return list;

		try {
			for (Object origObj : list) {
				Object newObj = clazz.newInstance();
				BeanUtil.copyProperties(origObj, newObj);
				newRst.add(newObj);
			}
		} catch (Exception e) {
		}

		return newRst;
	}

	/**
	 * javaBean对象Clone处理，这是深度复制方法，对象中的引用对象也会复制。 注意：不能进行串行化的对象一定要设成 transient
	 * 
	 * @param 旧对象
	 * @return 新对象
	 */
	@SuppressWarnings("unchecked")
	public static <T> T deepClone(T ob) {
		if (ob == null)
			return null;

		if (ob.getClass().toString().startsWith("class com.sun.proxy")) {
			return null;
		}
		ByteArrayOutputStream bo = new ByteArrayOutputStream();
		T newOb = null;
		try {
			ObjectOutputStream oo = new ObjectOutputStream(bo);
			oo.writeObject(ob);
			oo.close();
			ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
			ObjectInputStream oi = new ObjectInputStream(bi);
			newOb = (T) (oi.readObject());
			oi.close();
		} catch (Exception e) {
			//throw new GenericException(e);
		}
		return newOb;
	}
}
